Skip to content

feat: add pnpm lockfile v9 support - #198

Merged
sonukapoor merged 2 commits into
mainfrom
feature/issue-194-pnpm-v9-support
Apr 17, 2026
Merged

sonukapoor merged 2 commits into
mainfrom
feature/issue-194-pnpm-v9-support

Conversation

@sonukapoor

Copy link
Copy Markdown
Collaborator

Summary

  • Fixes false negatives on projects using pnpm lockfile v9 (lockfileVersion: '9.0') — the default since pnpm v8.6.0 (September 2023)
  • Preserves full backward compatibility with v5/v6 lockfiles
  • Corrects an existing test fixture that declared lockfileVersion: '9.0' while using v5/v6 package keys

Root cause

pnpm v9 introduced two breaking changes to the lockfile format:

  1. Package keys changed from /name/version to name@version
  2. The dependency graph moved from the packages section to a new snapshots section

The parser only handled the v5/v6 format, so all packages were silently skipped on v9 lockfiles.

Changes

src/parsers/pnpm-lock.ts

  • loadFromPnpmLock detects lockfileVersion and routes major ≥ 9 to loadV9, otherwise to loadLegacy
  • loadLegacy — existing logic extracted verbatim, zero behavior change
  • loadV9 — reads snapshots, uses name@version keys throughout
  • parsePnpmPackageKeyV9 — splits keys using lastIndexOf('@') for correct scoped package handling, strips peer-dep suffixes
  • normalizePnpmDepRefV9 — generates name@version graph keys
  • Both BFS loops now track visited keys (O(V+E)) instead of key+path combinations, preventing infinite traversal through circular dependencies present in real-world monorepos

tests/parsers.test.ts

  • Fixed existing fixture: lockfileVersion: '9.0''6.0'
  • New v9 test: snapshots format, scoped package, dev dep, transitive path, peer-dep suffix stripping

Verification

Tested against the Analog monorepo (pnpm-lock.yaml, 3367 packages, lockfileVersion 9.0):

  • Parser completes in ~333ms
  • 37 vulnerable packages found (previously: 0)

Closes #194

Corrects existing test fixture from lockfileVersion '9.0' to '6.0' —
the fixture uses v5/v6 package key format (/name/version) which is
inconsistent with a v9 declaration.

Adds a new test covering pnpm lockfile v9 format: snapshots section,
name@version keys, scoped packages, dev flag, transitive paths, and
peer-dep suffix stripping.
pnpm v9 changed two things that broke the parser: package keys moved
from /name/version to name@version format, and the dependency graph
moved from the packages section to a new snapshots section.

Adds version detection at parse entry — major >= 9 routes to loadV9,
everything else to loadLegacy (existing logic, extracted verbatim).

loadV9 reads snapshots for the dependency graph and dev flags.
parsePnpmPackageKeyV9 handles name@version keys using lastIndexOf('@')
to correctly split scoped packages and strip peer-dep suffixes.
normalizePnpmDepRefV9 generates name@version graph keys.

Both BFS loops now track visited keys rather than key+path combinations,
reducing complexity from exponential to O(V+E) and preventing infinite
traversal through circular dependencies present in real-world monorepos.
@sonukapoor
sonukapoor merged commit f254a1a into main Apr 17, 2026
4 checks passed
@sonukapoor
sonukapoor deleted the feature/issue-194-pnpm-v9-support branch April 17, 2026 17:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

pnpm lockfile v9 not supported — false negatives on modern pnpm projects

1 participant